package hu.monitor.agent.remoting;

import hu.monitor.remoting.InterceptorChain;
import hu.monitor.remoting.InvocationProxyFactory;

import java.io.IOException;

import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

public class EndpointRegistratorBeanFactoryPostProcessor implements BeanFactoryPostProcessor, ResourceLoaderAware {
	private ResourcePatternResolver resourceLoader;
	private final String resourcePattern;
	private final InterceptorChain chain;

	public EndpointRegistratorBeanFactoryPostProcessor(final String pattern, final InterceptorChain chain) {
		this.resourcePattern = pattern;
		this.chain = chain;
	}

	@Override
	public void setResourceLoader(final ResourceLoader resourceLoader) {
		this.resourceLoader = (ResourcePatternResolver) resourceLoader;
	}

	@Override
	public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException {
		final Resource[] resources;
		try {
			resources = this.resourceLoader.getResources(this.resourcePattern);
		} catch (final IOException ex) {
			throw new FatalBeanException(ex.getMessage(), ex);
		}

		final MetadataReaderFactory factory = new SimpleMetadataReaderFactory();
		for (final Resource resource : resources) {
			try {
				final MetadataReader reader = factory.getMetadataReader(resource);
				final ClassMetadata classMetadata = reader.getClassMetadata();
				final AnnotationMetadata metadata = reader.getAnnotationMetadata();

				if (metadata.hasAnnotation("javax.ejb.Remote")) {
					final String className = classMetadata.getClassName();
					final Class<?> remoteInterface = Class.forName(className);
					final InvocationProxyFactory proxyFactory = new InvocationProxyFactory(remoteInterface, this.chain);
					final InvocationProxyFactoryBean<Object> factoryBean = new InvocationProxyFactoryBean<Object>(proxyFactory);
					beanFactory.registerSingleton(remoteInterface.getName(), factoryBean);
				}
			} catch (final Exception ex) {
				throw new FatalBeanException("Error procesing resource: "+resource, ex);
			}
		}
	}

}
